package tidb

import (
	"github.com/pingcap/log"

	"github.com/pingcap-incubator/tidb-dashboard/pkg/config"
	"github.com/pingcap-incubator/tidb-dashboard/pkg/model"
)

const (
	DefaultInstanceID = -1
	NonInstanceID     = -999
)

type Factory struct {
	clientCache map[int]*Client
	config      *config.Config
}

func NewTiDBClientFactory(defaultClient *Client, config *config.Config) *Factory {
	clientCache := make(map[int]*Client)
	clientCache[DefaultInstanceID] = defaultClient
	if len(config.DatasourceKey) != 32 {
		log.Error("datasource key length is not 32 ")
	}
	return &Factory{clientCache, config}
}

func (f *Factory) GetClient(key int) *Client {
	return f.clientCache[key]
}

func (f *Factory) GetOrResisterClient(instance *model.TidbInstance) (*Client, error) {
	client := f.clientCache[int(instance.ID)]
	if client == nil || client.UpdateTime < instance.UpdateTime.Unix() {
		cli, err := f.RegisterClient(instance)
		if err != nil {
			return nil, err
		}
		client = cli
	}
	return client, nil
}

func (f *Factory) RegisterClient(instance *model.TidbInstance) (*Client, error) {
	err := DecryptInstanceParam(instance, f.config.DatasourceKey)
	if err != nil {
		return nil, err
	}
	client := &Client{
		lifecycleCtx:        nil,
		statusAPIHTTPScheme: "",
		statusAPIAddress:    "",
		statusAPIHTTPClient: nil,
		statusAPITimeout:    defaultTiDBStatusAPITimeout,
		sqlAPITLSKey:        "",
		SQLAPIAddress:       instance.Address,
		DefaultUsername:     instance.Username,
		DefaultPassword:     instance.Password,
		UpdateTime:          instance.UpdateTime.Unix(),
	}
	_, err = client.OpenSQLConn(instance.Username, instance.Password)
	if err != nil {
		return nil, err
	}
	f.clientCache[int(instance.ID)] = client
	return client, nil
}

func (f *Factory) GetDefaultClient() *Client {
	return f.GetClient(DefaultInstanceID)
}
